﻿using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.DataSourcesRaster;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geoprocessor;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geoprocessing;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.SpatialAnalystTools;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.SystemUI;

namespace School
{
    public partial class Slope : Form
    {
        private AxMapControl _mapControl;

        public Slope(AxMapControl mapControl)
        {
            InitializeComponent();
            _mapControl = mapControl;

            // Initialize dropdowns in constructor
            InitializeDropdowns();

            Load += Slope_Load;
        }

        private void InitializeDropdowns()
        {
            // Initialize these only once
            cboUnit.Items.Add("度");
            cboUnit.Items.Add("百分比");
            cboUnit.SelectedIndex = 0;

            cboMethod.Items.Add("平面");
            cboMethod.Items.Add("测地线");
            cboMethod.SelectedIndex = 0;

            cboZUnit.Items.Add("METER");
            cboZUnit.Items.Add("FOOT");
            cboZUnit.Items.Add("KILOMETER");
            cboZUnit.Items.Add("MILE_US");
            cboZUnit.Items.Add("NAUTICAL_MILE");
            cboZUnit.Items.Add("YARD");
            cboZUnit.Items.Add("INCH");
            cboZUnit.Items.Add("CENTIMETER");
            cboZUnit.Items.Add("MILLIMETER");
            cboZUnit.Items.Add("DECIMETER");
            cboZUnit.SelectedIndex = 0;

            // Set default Z factor
            txtZFactor.Text = "1";
        }

        private void Slope_Load(object sender, EventArgs e)
        {
            cboInput.Items.Clear();
            if (this._mapControl.LayerCount <= 0)
                return;

            ILayer pLayer;
            string strLayerName;
            for (int i = 0; i < this._mapControl.LayerCount; i++)
            {
                pLayer = this._mapControl.get_Layer(i);
                if (pLayer != null)
                {
                    strLayerName = pLayer.Name;
                    this.cboInput.Items.Add(strLayerName);
                }
            }
            if (cboInput.Items.Count > 0)
            {
                this.cboInput.SelectedIndex = 0;
            }

            string tempDir = @"D:\Temp\";
            if (cboInput.SelectedItem != null)
            {
                txtOutput.Text = System.IO.Path.Combine(tempDir, ((string)cboInput.SelectedItem + "_buffer.shp"));
            }

            cboInput.SelectedIndexChanged += CboInput_SelectedIndexChanged;
            UpdateZUnitFromSelectedRaster();
        }

        private void UpdateZUnitFromSelectedRaster()
        {
            try
            {
                string layerName = cboInput.SelectedItem?.ToString();
                if (string.IsNullOrEmpty(layerName)) return;

                IRasterLayer rasterLayer = GetRasterLayerByName(layerName);

                if (rasterLayer != null)
                {
                    string zUnit = AutoDetectZUnitFromRaster(rasterLayer);
                    if (!string.IsNullOrEmpty(zUnit))
                    {
                        // Just update the selection without clearing the items
                        for (int i = 0; i < cboZUnit.Items.Count; i++)
                        {
                            if (cboZUnit.Items[i].ToString() == zUnit)
                            {
                                cboZUnit.SelectedIndex = i;
                                break;
                            }
                        }
                    }
                }
                else
                {
                    MessageBox.Show($"所选图层 '{layerName}' 不是栅格图层，请选择栅格图层进行坡度分析。",
                        "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"自动检测Z单位时出错: {ex.Message}",
                               "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        private void CboInput_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateZUnitFromSelectedRaster();
        }

        private string AutoDetectZUnitFromRaster(IRasterLayer rasterLayer)
        {
            try
            {
                IRaster2 raster = (IRaster2)rasterLayer.Raster;
                IRasterDataset rasterDataset = raster.RasterDataset;

                ISpatialReference spatialRef = null;
                if (rasterDataset is IGeoDataset geoDataset)
                {
                    spatialRef = geoDataset.SpatialReference;
                }

                if (spatialRef != null)
                {
                    int wkid = spatialRef.FactoryCode;
                    if (wkid != 0 && wkid != 4326) // 4326为未指定投影的地理坐标系
                    {
                        ILinearUnit linearUnit = spatialRef.ZCoordinateUnit as ILinearUnit;
                        if (linearUnit != null)
                        {
                            // 替代Type属性：通过单位名称映射单位类型
                            string unitName = linearUnit.Name.ToUpperInvariant();

                            if (unitName.Contains("METER"))
                                return "METER";
                            else if (unitName.Contains("FOOT") || unitName.Contains("FEET"))
                                return "FOOT";
                            else if (unitName.Contains("KILOMETER"))
                                return "KILOMETER";
                            else if (unitName.Contains("MILE"))
                                return "MILE_US";
                            else if (unitName.Contains("NAUTICAL"))
                                return "NAUTICAL_MILE";
                            else if (unitName.Contains("YARD"))
                                return "YARD";
                            else if (unitName.Contains("INCH"))
                                return "INCH";
                            else if (unitName.Contains("CENTIMETER"))
                                return "CENTIMETER";
                            else if (unitName.Contains("MILLIMETER"))
                                return "MILLIMETER";
                            else if (unitName.Contains("DECIMETER"))
                                return "DECIMETER";
                            else
                                return "METER"; // 默认使用米
                        }
                    }
                }

                return "METER"; // 如果无法检测，默认使用米
            }
            catch (Exception ex)
            {
                MessageBox.Show($"获取栅格空间参考时出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return "METER"; // 出错时默认使用米
            }
        }

        private void btnOutput_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveDlg = new SaveFileDialog();
            saveDlg.CheckPathExists = true;
            saveDlg.Filter = "Shapefile (*.shp)|*.shp";
            saveDlg.OverwritePrompt = true;
            saveDlg.Title = "输出路径";
            saveDlg.RestoreDirectory = true;
            if (cboInput.SelectedItem != null)
            {
                saveDlg.FileName = (string)cboInput.SelectedItem + "_buffer.shp";
            }

            //读取文件输出路径到txtOutputPath
            DialogResult dr = saveDlg.ShowDialog();
            if (dr == DialogResult.OK)
            {
                txtOutput.Text = saveDlg.FileName;
            }
        }

        private void ExecuteSlopeAnalysis(IRasterLayer inputRasterLayer)
        {
            try
            {
                // 显示进度提示
                Cursor = Cursors.WaitCursor;
                MessageBox.Show("开始执行坡度分析，请稍候...", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);

                Geoprocessor gp = new Geoprocessor();
                gp.OverwriteOutput = true;

                ESRI.ArcGIS.SpatialAnalystTools.Slope slopeTool = new ESRI.ArcGIS.SpatialAnalystTools.Slope();
                slopeTool.in_raster = inputRasterLayer.Raster;

                string outputPath = System.IO.Path.Combine(
                    System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location),
                    "SlopeOutput.tif");
                slopeTool.out_raster = outputPath;

                if (cboUnit.SelectedItem != null)
                {
                    string selectedUnit = cboUnit.SelectedItem.ToString();
                    slopeTool.output_measurement = selectedUnit == "度" ? "DEGREE" : "PERCENT_RISE";
                }

                if (cboMethod.SelectedItem != null)
                {
                    string selectedMethod = cboMethod.SelectedItem.ToString();
                    slopeTool.method = selectedMethod == "平面" ? "PLANAR" : "GEODESIC";
                }

                if (cboZUnit.SelectedItem != null)
                {
                    slopeTool.z_unit = cboZUnit.SelectedItem.ToString();
                }

                if (!string.IsNullOrEmpty(txtZFactor.Text) && double.TryParse(txtZFactor.Text, out double zFactor))
                {
                    slopeTool.z_factor = zFactor;
                }

                // 执行分析
                IGeoProcessorResult result = (IGeoProcessorResult)gp.Execute(slopeTool, null);

                if (result.Status == esriJobStatus.esriJobSucceeded)
                {
                    string outputRasterPath = result.GetOutput(0).GetAsText();

                    IRasterLayer outputLayer = new RasterLayerClass();
                    outputLayer.CreateFromFilePath(outputRasterPath);
                    outputLayer.Name = "坡度分析结果";

                    _mapControl.AddLayer((ILayer)outputLayer);
                    _mapControl.Refresh();

                    MessageBox.Show("坡度分析完成！结果已添加到地图中。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    string message = string.Join("\r\n", Enumerable.Range(0, gp.MessageCount).Select(i => gp.GetMessage(i)));
                    MessageBox.Show($"分析完成但状态异常: {message}", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"执行坡度分析时出错：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                Cursor = Cursors.Default;
            }
        }

        private IRasterLayer GetRasterLayerByName(string layerName)
        {
            // 调试输出：显示所有图层名称，帮助诊断问题
            System.Diagnostics.Debug.WriteLine("地图控件中的所有图层：");
            for (int i = 0; i < _mapControl.LayerCount; i++)
            {
                ILayer layer = _mapControl.get_Layer(i);
                if (layer != null)
                {
                    System.Diagnostics.Debug.WriteLine($"  {i}: {layer.Name} ({layer.GetType().FullName})");
                }
            }

            for (int i = 0; i < _mapControl.LayerCount; i++)
            {
                ILayer layer = _mapControl.get_Layer(i);
                if (layer != null && layer.Name == layerName)
                {
                    if (layer is IRasterLayer rasterLayer)
                    {
                        System.Diagnostics.Debug.WriteLine($"找到栅格图层: {layerName}");
                        return rasterLayer;
                    }
                    else
                    {
                        System.Diagnostics.Debug.WriteLine($"找到图层但不是栅格类型: {layerName} ({layer.GetType().FullName})");
                    }
                }
            }

            System.Diagnostics.Debug.WriteLine($"未找到栅格图层: {layerName}");
            return null;
        }

        // 坡度分析按钮点击事件
        private void btnAnalyze_Click(object sender, EventArgs e)
        {
            if (cboInput.SelectedItem == null)
            {
                MessageBox.Show("请先选择输入图层", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            string selectedLayerName = cboInput.SelectedItem.ToString();
            IRasterLayer inputRasterLayer = GetRasterLayerByName(selectedLayerName);

            if (inputRasterLayer == null)
            {
                // 显示详细的错误信息，帮助用户理解问题
                StringBuilder message = new StringBuilder();
                message.AppendLine($"找不到所选的栅格图层: '{selectedLayerName}'");
                message.AppendLine();
                message.AppendLine("请确保：");
                message.AppendLine("1. 已正确添加栅格图层到地图中");
                message.AppendLine("2. 从下拉列表中选择的是栅格图层（而不是矢量图层）");
                message.AppendLine("3. 图层名称没有拼写错误");

                MessageBox.Show(message.ToString(), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);

                // 调试信息：显示当前地图中的所有图层
                System.Diagnostics.Debug.WriteLine("当前地图中的图层列表：");
                for (int i = 0; i < _mapControl.LayerCount; i++)
                {
                    ILayer layer = _mapControl.get_Layer(i);
                    if (layer != null)
                    {
                        System.Diagnostics.Debug.WriteLine($"  {i}: {layer.Name} ({layer.GetType().Name})");
                    }
                }

                return;
            }

            try
            {
                ExecuteSlopeAnalysis(inputRasterLayer);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"坡度分析失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnBack_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnInput_Click(object sender, EventArgs e)
        {
            var form = new Form()
            {
                Text = "选择输入数据",
                Width = 600,
                Height = 500,
                FormBorderStyle = FormBorderStyle.FixedDialog
            };

            // 保存当前UI状态
            string currentUnit = cboUnit.SelectedItem?.ToString();
            string currentZUnit = cboZUnit.SelectedItem?.ToString();
            string currentMethod = cboMethod.SelectedItem?.ToString();
            string currentZFactor = txtZFactor.Text;

            // 保存测量单位下拉框的内容
            var unitItems = new List<string>();
            for (int i = 0; i < cboUnit.Items.Count; i++)
            {
                unitItems.Add(cboUnit.Items[i].ToString());
            }

            var tabControl = new TabControl() { Dock = DockStyle.Fill };

            // Tab1: 地理数据库选择
            var tabGDB = new TabPage("地理数据库");
            var listBox = new ListBox()
            {
                Width = 400,
                Height = 300,
                Top = 50,
                Left = 20,
                DisplayMember = "DisplayName"
            };

            var btnBrowse = new Button()
            {
                Text = "选择GDB文件夹",
                Width = 150,
                Top = 20,
                Left = 20
            };

            // 将folderDlg声明移到方法作用域
            string selectedGdbPath = null;

            btnBrowse.Click += (s, args) =>
            {
                using (var folderDlg = new FolderBrowserDialog())
                {
                    folderDlg.Description = "选择文件地理数据库(.gdb)文件夹";
                    if (folderDlg.ShowDialog() == DialogResult.OK &&
                        IsValidGdbFolder(folderDlg.SelectedPath))
                    {
                        selectedGdbPath = folderDlg.SelectedPath; // 保存选择的路径
                        LoadGdbContents(folderDlg.SelectedPath, listBox);
                    }
                }
            };

            var btnSelect = new Button()
            {
                Text = "确认选择",
                Width = 150,
                Top = 360,
                Left = 20,
                Enabled = false
            };

            listBox.SelectedIndexChanged += (s, args) =>
            {
                btnSelect.Enabled = listBox.SelectedItem != null;
            };

            btnSelect.Click += (s, args) =>
            {
                var selectedItem = listBox.SelectedItem as GdbItem;
                if (selectedItem != null && !string.IsNullOrEmpty(selectedGdbPath))
                {
                    AddInputLayer(selectedGdbPath, selectedItem.Name);

                    RestoreUnitComboBox(unitItems);
                    UpdateZUnitFromSelectedRaster();

                    // 恢复选择状态
                    if (currentUnit != null) cboUnit.SelectedItem = currentUnit;
                    if (currentZUnit != null) cboZUnit.SelectedItem = currentZUnit;

                    form.Close();
                }
            };

            tabGDB.Controls.AddRange(new Control[] { btnBrowse, listBox, btnSelect });
            tabControl.TabPages.Add(tabGDB);
            form.Controls.Add(tabControl);

            if (form.ShowDialog() == DialogResult.OK)
            {
                // 恢复UI状态
                if (!string.IsNullOrEmpty(currentUnit))
                    cboUnit.SelectedItem = currentUnit;
                if (!string.IsNullOrEmpty(currentZUnit))
                    cboZUnit.SelectedItem = currentZUnit;
                if (!string.IsNullOrEmpty(currentMethod))
                    cboMethod.SelectedItem = currentMethod;
                txtZFactor.Text = currentZFactor;
            }
        }

        private void AddInputLayer(string gdbPath, string datasetName)
        {
            try
            {
                IWorkspaceFactory wsFactory = new FileGDBWorkspaceFactoryClass();
                IWorkspace workspace = wsFactory.OpenFromFile(gdbPath, 0);

                // 正确获取数据集的方法
                IEnumDataset enumDatasets = workspace.get_Datasets(esriDatasetType.esriDTAny);
                IDataset dataset = enumDatasets.Next();

                while (dataset != null)
                {
                    if (dataset.Name == datasetName && IsRasterDataset(dataset))
                    {
                        break;
                    }
                    dataset = enumDatasets.Next();
                }

                if (dataset != null && IsRasterDataset(dataset))
                {
                    IRasterLayer rasterLayer = new RasterLayerClass();
                    IRasterDataset rasterDataset = dataset as IRasterDataset;
                    rasterLayer.CreateFromDataset(rasterDataset);
                    rasterLayer.Name = datasetName;

                    _mapControl.AddLayer((ILayer)rasterLayer);
                    _mapControl.Refresh();

                    cboInput.Items.Add(datasetName);
                    cboInput.SelectedIndex = cboInput.Items.Count - 1;

                    MessageBox.Show($"成功添加栅格图层: {datasetName}", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    MessageBox.Show($"名称为 '{datasetName}' 的数据集不是有效的栅格数据集", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"添加输入图层失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private bool IsRasterDataset(IDataset dataset)
        {
            return dataset != null && dataset.Type == esriDatasetType.esriDTRasterDataset;
        }

        private void RestoreUnitComboBox(List<string> items)
        {
            cboUnit.Items.Clear();
            foreach (var item in items)
            {
                cboUnit.Items.Add(item);
            }
        }

       

        // 辅助类：存储GDB项信息
        private class GdbItem
        {
            public string Name { get; set; }
            public string DisplayName { get; set; }
            public esriDatasetType DataType { get; set; }
        }

        // 检查是否为有效GDB文件夹
        private bool IsValidGdbFolder(string path)
        {
            return Directory.Exists(path) &&
                   System.IO.Path.GetExtension(path).Equals(".gdb", StringComparison.OrdinalIgnoreCase);
        }

        private void LoadGdbContents(string gdbPath, ListBox listBox)
        {
            try
            {
                listBox.Items.Clear();
                IWorkspaceFactory wsFactory = new FileGDBWorkspaceFactoryClass();
                IWorkspace workspace = wsFactory.OpenFromFile(gdbPath, 0);

                IEnumDataset enumDS = workspace.get_Datasets(esriDatasetType.esriDTAny);
                IDataset ds = enumDS.Next();

                while (ds != null)
                {
                    var item = new GdbItem()
                    {
                        Name = ds.Name,
                        DisplayName = $"{ds.Name} ({GetDataTypeName(ds.Type)})",
                        DataType = ds.Type
                    };

                    if (IsRasterDataset(ds))
                    {
                        listBox.Items.Add(item);
                    }

                    ds = enumDS.Next();
                }

                if (listBox.Items.Count == 0)
                {
                    MessageBox.Show("在所选地理数据库中未找到栅格数据集", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"加载地理数据库内容失败:\n{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        // 获取数据类型友好名称
        private string GetDataTypeName(esriDatasetType dataType)
        {
            switch (dataType)
            {
                case esriDatasetType.esriDTFeatureClass: return "要素类";
                case esriDatasetType.esriDTRasterDataset: return "栅格";
                default: return dataType.ToString();
            }
        }
    }
}